package com.manager.commons.utils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;

/**
 * 数据格式化
 *
 * @author wangchaoyong
 */
public class NumberUtil {
    // 默认除法运算精度
    private static final Integer DEF_DIV_SCALE = 2;
    private static final Integer ROUND = BigDecimal.ROUND_HALF_UP;

    /**
     * 提供精确的加法运算。
     *
     * @param value1 被加数
     * @param value2 加数
     * @return 两个参数的和
     */
    public static BigDecimal add(Number value1, Number value2) {
        BigDecimal b1 = new BigDecimal(Double.toString(value1.doubleValue()));
        BigDecimal b2 = new BigDecimal(Double.toString(value2.doubleValue()));
        return b1.add(b2);
    }

    /**
     * 提供精确的加法运算。
     *
     * @param value1 被加数
     * @param value2 加数
     * @return 两个参数的和
     */
    public static Double add(String value1, String value2) {
        BigDecimal b1 = new BigDecimal(value1);
        BigDecimal b2 = new BigDecimal(value2);
        return b1.add(b2).doubleValue();
    }

    /**
     * 提供精确的减法运算。
     *
     * @param value1 被减数
     * @param value2 减数
     * @return 两个参数的差
     */
    public static double sub(Number value1, Number value2) {
        BigDecimal b1 = new BigDecimal(Double.toString(value1.doubleValue()));
        BigDecimal b2 = new BigDecimal(Double.toString(value2.doubleValue()));
        return b1.subtract(b2).doubleValue();
    }

    /**
     * 提供精确的乘法运算。
     *
     * @param value1 被乘数
     * @param value2 乘数
     * @return 两个参数的积
     */
    public static BigDecimal mul(Number value1, Number value2) {
        BigDecimal b1 = new BigDecimal(Double.toString(value1.doubleValue()));
        BigDecimal b2 = new BigDecimal(Double.toString(value2.doubleValue()));
        return b1.multiply(b2);
    }

    /**
     * 提供（相对）精确的除法运算，当发生除不尽的情况时， 精确到小数点以后10位，以后的数字四舍五入。
     *
     * @param dividend 被除数
     * @param divisor  除数
     * @return 两个参数的商
     */
    public static BigDecimal div(BigDecimal dividend, BigDecimal divisor) {
        return div(dividend, divisor, DEF_DIV_SCALE);
    }

    public static BigDecimal div(BigDecimal dividend, Integer divisor) {
        return div(dividend, new BigDecimal(divisor), DEF_DIV_SCALE);
    }

    public static BigDecimal div(BigDecimal dividend, Double divisor) {
        return div(dividend, new BigDecimal(divisor), DEF_DIV_SCALE);
    }

    /**
     * 提供（相对）精确的除法运算。 当发生除不尽的情况时，由scale参数指定精度，以后的数字四舍五入。
     *
     * @param dividend 被除数
     * @param divisor  除数
     * @param scale    表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    public static BigDecimal div(BigDecimal dividend, BigDecimal divisor, Integer scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        try {
            return dividend.divide(divisor, scale, ROUND);
        } catch (Exception e) {
            return new BigDecimal(0);
        }

    }

    /**
     * 提供精确的小数位四舍五入处理。
     *
     * @param value 需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static Double round(double value, Integer scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(value));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, ROUND).doubleValue();
    }

    /**
     * 提供精确的小数位四舍五入处理。
     *
     * @param value 需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static String getString(Double value, Integer scale) {
        value = round(value, scale);
        String str = String.valueOf(value);
        StringBuffer sb = new StringBuffer(str);
        int leng = str.substring(str.indexOf(".") + 1).length();
        for (int i = 0; i < scale - leng; i++) {
            sb.append("0");
        }
        return sb.toString();
    }

    public static String getString(BigDecimal value, Integer scale) {
        Double value1 = round(value.doubleValue(), scale);
        String str = String.valueOf(value1);
        StringBuffer sb = new StringBuffer(str);
        int leng = str.substring(str.indexOf(".") + 1).length();
        for (int i = 0; i < scale - leng; i++) {
            sb.append("0");
        }
        return sb.toString();
    }

    /**
     * 提供精确的小数位四舍五入处理。
     *
     * @param value 需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static String getString(int value, Integer scale) {
        String str = String.valueOf(value);
        StringBuffer sb = new StringBuffer(str);
        sb.append(".");
        for (int i = 0; i < scale; i++) {
            sb.append("0");
        }
        return sb.toString();
    }

    /**
     * 提供精确的小数位四舍五入处理。
     *
     * @param value 需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static String getString(String value, Integer scale) {
        return getString(Double.valueOf(value), scale);
    }

    public static String getNumberSString(BigDecimal decimal) {
        if (decimal == null) {
            return "0.00";
        }
        DecimalFormat df = new DecimalFormat("###,###.##");
        df.setMinimumFractionDigits(2);
        return df.format(decimal.doubleValue());
    }

    public static String getNumberWString(BigDecimal decimal) {
        if (decimal == null) {
            return "0.00";
        }
        DecimalFormat df = new DecimalFormat("###,###.##");
        df.setMinimumFractionDigits(2);
        return df.format(decimal.divide(new BigDecimal("10000"), 2, RoundingMode.DOWN).doubleValue());
    }

    public static String getNumberSString(BigDecimal decimal, int size) {
        StringBuffer str = new StringBuffer();
        if (decimal == null) {
            str.append("0");
            if (size > 0) {
                str.append(".");
                for (int i = 0; i < size; i++) {
                    str.append("0");
                }
            }
            return str.toString();
        }
        DecimalFormat df = null;
        if (size > 0) {
            str.append("###,###");
            str.append(".");
            for (int i = 0; i < size; i++) {
                str.append("#");
            }
            df = new DecimalFormat(str.toString());
            df.setMinimumFractionDigits(size);
        } else {
            df = new DecimalFormat("###,###");
            df.setMinimumFractionDigits(0);
        }
        return df.format(decimal.doubleValue());
    }

    public static String getNumberWString(BigDecimal decimal, int size) {
        StringBuffer str = new StringBuffer();
        if (decimal == null) {
            str.append("0");
            if (size > 0) {
                str.append(".");
                for (int i = 0; i < size; i++) {
                    str.append("0");
                }
            }
            return str.toString();
        }
        DecimalFormat df = null;
        if (size > 0) {
            str.append("###,###");
            str.append(".");
            for (int i = 0; i < size; i++) {
                str.append("#");
            }
            df = new DecimalFormat(str.toString());
            df.setMinimumFractionDigits(size);
        } else {
            df = new DecimalFormat("###,###");
            df.setMinimumFractionDigits(0);
        }
        return df.format(decimal.divide(new BigDecimal("10000"), size, RoundingMode.DOWN).doubleValue());
    }

    /**
     * 除法运算
     *
     * @param b1 除数
     * @param b2 被除数
     * @return BigDecimal
     */
    public static BigDecimal getRatio(BigDecimal b1, BigDecimal b2) {
        if (b1 == null || b2 == null || b2.doubleValue() <= 0.00) {
            return new BigDecimal("0.00");
        } else {
            return b1.divide(b2, 4, RoundingMode.DOWN);
        }
    }

    public static BigDecimal getRatio(BigDecimal b1, Integer b2) {
        if (b1 == null || b2 == null || b2 <= 0.00) {
            return new BigDecimal("0.00");
        } else {
            return b1.divide(new BigDecimal(b2), 4, RoundingMode.DOWN);
        }
    }

    /**
     * 百分比
     *
     * @param b1
     * @return
     */
    public static BigDecimal Percentage(BigDecimal b1) {
        if (b1 == null) {
            return new BigDecimal("0.00");
        } else {
            return b1.divide(new BigDecimal(100), 4, RoundingMode.DOWN);
        }
    }

    /**
     * 乘以100
     *
     * @param b1
     * @return
     */
    public static BigDecimal Multiply(BigDecimal b1) {
        if (b1 == null) {
            return new BigDecimal("0.00");
        } else {
            return b1.multiply(new BigDecimal(100));
        }
    }

    public static BigDecimal getRatio(Integer b1, Integer b2) {
        if (b1 == null || b2 == null || b2 <= 0) {
            return new BigDecimal("0.00");
        } else {
            return getRatio(new BigDecimal(b1), new BigDecimal(b2));

        }
    }

    public static String getRatioS(BigDecimal b) {
        return (new BigDecimal("100")).multiply(b).setScale(2) + "%";
    }

    public static String getRatioS(Integer b1, Integer b2) {
        return getRatioS(getRatio(b1, b2));
    }

    public static String getRatioS(BigDecimal b1, BigDecimal b2) {
        return getRatioS(getRatio(b1, b2));
    }

    /**
     * 格式数字为字符串
     *
     * @param decimal
     * @return
     */
    public static String getNumberFormat(BigDecimal decimal) {
        if (decimal == null) {
            decimal = new BigDecimal(0);
        }
        if (decimal.intValue() >= 10000) {
            return getNumberSString(decimal) + "万";
        } else {
            return getNumberWString(decimal);
        }
    }

    /**
     * 格式数字为字符串
     *
     * @param decimal
     * @return
     */
    public static BigDecimal getNumberFormat(String decimal) {
        if (StringUtil.isNotEmpty(decimal)) {
            if (StringUtil.isNumberic(decimal)) {
                return new BigDecimal(decimal);
            }
        }
        return new BigDecimal(0);
    }

    public static Integer getMax(Integer max, int splitNumber) {
        if (splitNumber > 0 && max > splitNumber) {
            BigDecimal a = new BigDecimal(max).divide(new BigDecimal(splitNumber), RoundingMode.UP);
            a = a.multiply(new BigDecimal(splitNumber));
            return a.intValue();
        } else {
            return max > splitNumber ? max : splitNumber;
        }
    }

    public static int getInteger(String number) {
        try {
            if (StringUtil.isNotEmpty(number)) {
                return Integer.parseInt(number);
            }
        } catch (Exception ignored) {
        }
        return 0;
    }
}
